package com.sky.websocket;

import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {

    // 存放会话对象，使用线程安全的Map
    private static Map<String, Session> sessionMap = Collections.synchronizedMap(new HashMap<>());

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客户端：" + sid + "建立连接，当前连接数：" + sessionMap.size());
        sessionMap.put(sid, session);
        // 可在此处添加连接成功的通知消息
        sendToClient("连接成功", sid);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param sid     客户端标识
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端：" + sid + "的信息:" + message);

        // 示例：收到消息后可以直接转发给所有客户端
        // sendToAllClient("客户端" + sid + "说：" + message);
    }

    /**
     * 连接关闭调用的方法
     *
     * @param sid 客户端标识
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("连接断开:" + sid);
        sessionMap.remove(sid);
        System.out.println("当前剩余连接数：" + sessionMap.size());
    }

    /**
     * 发生错误时调用
     *
     * @param session 会话对象
     * @param error   错误信息
     * @param sid     客户端标识
     */
    @OnError
    public void onError(Session session, Throwable error, @PathParam("sid") String sid) {
        System.out.println("发生错误：" + sid + ",错误信息：" + error.getMessage());
        error.printStackTrace();

        // 错误发生后可以选择关闭连接
        try {
            if (session.isOpen()) {
                session.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        sessionMap.remove(sid);
    }

    /**
     * 群发消息
     *
     * @param message 消息内容
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                // 确保会话处于打开状态
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(message);
                }
            } catch (IOException e) {
                System.err.println("群发消息失败：" + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * 向指定客户端发送消息
     *
     * @param message 消息内容
     * @param sid     客户端标识
     */
    public void sendToClient(String message, String sid) {
        Session session = sessionMap.get(sid);
        if (session != null && session.isOpen()) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                System.err.println("向客户端" + sid + "发送消息失败：" + e.getMessage());
                e.printStackTrace();
            }
        } else {
            System.out.println("客户端" + sid + "连接已关闭或不存在");
        }
    }

    /**
     * 获取当前在线客户端数量
     * @return 在线客户端数量
     */
    public int getOnlineCount() {
        return sessionMap.size();
    }
}
